import tkinter as tk
from tkinter import ttk, messagebox
import psutil
import serial
import serial.tools.list_ports
import threading
import time
import platform
import queue

class CPUMonitor:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("CPU Monitor")
        self.root.geometry("400x300")
        
        # 变量初始化
        self.running = True  # 程序运行标志
        self.connected = False  # 串口连接标志
        self.serial_port = None
        self.update_thread = None
        self.port_scanner_thread = None
        self.update_interval = tk.DoubleVar(value=2.0)  # 默认2秒
        self.serial_queue = queue.Queue()  # 用于串口数据接收
        
        self._init_gui()
        self._start_port_scanner()
        
    def _init_gui(self):
        # 状态显示
        status_frame = ttk.LabelFrame(self.root, text="连接状态", padding=5)
        status_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.status_label = ttk.Label(status_frame, text="搜索设备中...")
        self.status_label.pack(pady=5)
        
        # CPU使用率显示
        cpu_frame = ttk.LabelFrame(self.root, text="CPU使用率", padding=5)
        cpu_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.cpu_label = ttk.Label(cpu_frame, text="0%", font=("Arial", 24))
        self.cpu_label.pack(pady=10)
        
        self.progress = ttk.Progressbar(cpu_frame, length=300, mode='determinate')
        self.progress.pack(pady=5)
        
        # 更新频率设置
        freq_frame = ttk.LabelFrame(self.root, text="更新频率", padding=5)
        freq_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.freq_scale = ttk.Scale(freq_frame, from_=0.5, to=60.0, 
                                  variable=self.update_interval,
                                  orient=tk.HORIZONTAL)
        self.freq_scale.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        
        self.freq_label = ttk.Label(freq_frame, text="2.0 秒")
        self.freq_label.pack(side=tk.LEFT, padx=5)
        
        # 绑定频率更新事件
        self.freq_scale.bind("<Motion>", self._update_freq_label)
        
    def _start_port_scanner(self):
        """启动串口扫描线程"""
        self.port_scanner_thread = threading.Thread(target=self._scan_ports, daemon=True)
        self.port_scanner_thread.start()
        
    def _scan_ports(self):
        """扫描可用串口并尝试连接"""
        while self.running:
            if not self.connected:
                ports = list(serial.tools.list_ports.comports())
                for port in ports:
                    try:
                        # 尝试打开串口
                        ser = serial.Serial(port.device, 115200, timeout=1)
                        # 等待并检查是否收到"ready"
                        time.sleep(3.5)  # 等待超过设备的3秒发送周期
                        if ser.in_waiting:
                            data = ser.readline().decode().strip().lower()
                            if data == "ready":
                                self.serial_port = ser
                                self.connected = True
                                self.root.after(0, self._update_status, f"已连接到 {port.device}")
                                # 启动CPU监控线程
                                self.update_thread = threading.Thread(target=self._update_cpu, daemon=True)
                                self.update_thread.start()
                                break
                        ser.close()
                    except:
                        continue
                if not self.connected:
                    self.root.after(0, self._update_status, "搜索设备中...")
            time.sleep(1)  # 避免过于频繁的扫描
            
    def _update_status(self, message):
        """更新状态显示"""
        self.status_label.config(text=message)
            
    def _update_freq_label(self, event=None):
        """更新频率显示标签"""
        value = self.update_interval.get()
        self.freq_label.config(text=f"{value:.1f} 秒")
        
    def _update_cpu(self):
        """CPU使用率更新线程"""
        last_send_time = time.time()
        
        while self.running and self.connected:
            try:
                current_time = time.time()
                
                # 检查串口是否有数据
                if self.serial_port.in_waiting:
                    data = self.serial_port.readline().decode().strip().lower()
                    if data == "ready":
                        last_send_time = current_time
                
                # 如果超过8秒没有收到ready，认为连接断开
                if current_time - last_send_time > 8:
                    self.connected = False
                    self.serial_port.close()
                    self.root.after(0, self._update_status, "设备断开，重新搜索...")
                    break
                
                cpu_percent = psutil.cpu_percent(interval=0.1)
                value = int(cpu_percent * 10)
                value = min(1000, max(0, value))
                
                # 更新GUI
                self.root.after(0, self._update_gui, cpu_percent, value)
                
                # 发送数据
                if self.serial_port and self.serial_port.is_open:
                    self.serial_port.write(f"{value}\n".encode())
                    
                time.sleep(self.update_interval.get())
                
            except Exception as e:
                print(f"Error: {str(e)}")
                self.connected = False
                if self.serial_port:
                    self.serial_port.close()
                self.root.after(0, self._update_status, "连接错误，重新搜索...")
                break
                
    def _update_gui(self, cpu_percent, value):
        """更新GUI显示"""
        self.cpu_label.config(text=f"{cpu_percent:.1f}%")
        self.progress['value'] = cpu_percent
        
    def run(self):
        """启动主循环"""
        try:
            self.root.mainloop()
        finally:
            self.running = False
            if self.serial_port:
                self.serial_port.close()
        
if __name__ == "__main__":
    app = CPUMonitor()
    app.run() 